home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / SpriteFight 2002 v2.0a1 / SpriteWorldUtils.c < prev    next >
Encoding:
Text File  |  1994-04-25  |  31.3 KB  |  1,339 lines  |  [TEXT/KAHL]

  1. ///--------------------------------------------------------------------------------------
  2. //    SpriteWorldUtils.c
  3. //
  4. //    Created:    Monday, January 18, 1993 at 8:57:36 PM
  5. //    By:        Tony Myles
  6. //
  7. //    Copyright: © 1993-94 Tony Myles, All rights reserved worldwide.
  8. //
  9. //    Description:    some utilities for creating worlds of sprites
  10. ///--------------------------------------------------------------------------------------
  11.  
  12.  
  13. #ifndef __SWCOMMON__
  14. #include "SWCommonHeaders.h"
  15. #endif
  16.  
  17. #ifndef __QUICKDRAW__
  18. #include <QuickDraw.h>
  19. #endif
  20.  
  21. #ifndef __QDOFFSCREEN__
  22. #include <QDOffscreen.h>
  23. #endif
  24.  
  25. #ifndef __WINDOWS__
  26. #include <Windows.h>
  27. #endif
  28.  
  29. #ifndef __MEMORY__
  30. #include <Memory.h>
  31. #endif
  32.  
  33. #ifndef __GESTALTEQU__
  34. #include <GestaltEqu.h>
  35. #endif
  36.  
  37. #ifndef __TOOLUTILS__
  38. #include <ToolUtils.h>
  39. #endif
  40.  
  41. #ifndef __RESOURCES__
  42. #include <Resources.h>
  43. #endif
  44.  
  45. #ifndef __ERRORS__
  46. #include <Errors.h>
  47. #endif
  48.  
  49. #ifndef __SPRITEWORLD__
  50. #include "SpriteWorld.h"
  51. #endif
  52.  
  53. #ifndef __SPRITELAYER__
  54. #include "SpriteLayer.h"
  55. #endif
  56.  
  57. #ifndef __SPRITE__
  58. #include "Sprite.h"
  59. #endif
  60.  
  61. #ifndef __FRAME__
  62. #include "Frame.h"
  63. #endif
  64.  
  65. #ifndef __SPRITEWORLDUTILS__
  66. #include "SpriteWorldUtils.h"
  67. #endif
  68.  
  69. #if MPW
  70. #pragma segment SpriteWorld
  71. #endif
  72.  
  73. ///--------------------------------------------------------------------------------------
  74. // SWCreateBestCGrafPort                                        Adapted from code by Forrest Tanaka
  75. ///--------------------------------------------------------------------------------------
  76.  
  77. SW_FUNC OSErr SWCreateBestCGrafPort(
  78.     CGrafPtr    *newCGrafPort,                    // returns a pointer to the new CGrafPort
  79.     Rect        *offScreenRect)                // global rectangle of part of screen to save
  80. {
  81.     OSErr                err;                        // err code
  82.     GDHandle            baseGDevice;            // GDevice to base off-screen on
  83.     PixMapHandle    basePixMap;                // baseGDevice’s PixMap
  84.     Rect                tempOffScreenRect;    // temp rect used for adjustments
  85.  
  86.     err = noErr;
  87.  
  88.         // graphics devices manager tells us the deepest intersecting screen
  89.     baseGDevice = GetMaxDevice(offScreenRect);
  90.  
  91.         // if no screens intersect the bounds, baseDevice is NULL
  92.     if ((baseGDevice != NULL) && (err == noErr))
  93.     {
  94.             // normalize the bounds rectangle
  95.         tempOffScreenRect = *offScreenRect;
  96.         OffsetRect(&tempOffScreenRect, -tempOffScreenRect.left, -tempOffScreenRect.top);
  97.  
  98.             // create off-screen graphics environment w/ depth, clut of screen
  99.         basePixMap = (**baseGDevice).gdPMap;
  100.         err = SWCreateCGrafPort(newCGrafPort, &tempOffScreenRect, (**basePixMap).pixelSize,
  101.                                 (**basePixMap).pmTable, baseGDevice);
  102.     }
  103.  
  104.     return err;
  105. }
  106.  
  107.  
  108. ///--------------------------------------------------------------------------------------
  109. // SWCreateOffScreen                                                Adapted from code by Forrest Tanaka
  110. ///--------------------------------------------------------------------------------------
  111.  
  112. #define kMaxRowBytes 0x3FFE // Maximum number of bytes in a row of pixels
  113.  
  114. SW_FUNC OSErr SWCreateCGrafPort(
  115.     CGrafPtr        *newCGrafPort,        // returns a pointer to the new CGrafPort
  116.     Rect            *bounds,                // bounding rectangle of off-screen
  117.     short            depth,                // desired number of bits per pixel in off-screen
  118.     CTabHandle    colors,                // color table to assign to off-screen
  119.     GDHandle        useGDevice)            // returns a handle to the new GDevice
  120. {
  121.     CGrafPtr            tempCGrafPort;    // pointer to the new off-screen CGrafPort
  122.     PixMapHandle    newPixMap;        // handle to the new off-screen PixMap
  123.     GDHandle            newDevice;        // handle to the new off-screen GDevice
  124.     long                qdVersion;        // version of QuickDraw currently in use
  125.     GrafPtr            savedPort;        // pointer to GrafPort used for save/restore
  126.     SignedByte        savedState;        // saved state of color table handle
  127.     short                bytesPerRow;    // number of bytes per row in the PixMap
  128.     OSErr                err;                // returns err code
  129.  
  130. #if MPW
  131. #pragma unused(useGDevice)
  132. #endif
  133.  
  134.         // initialize a few things before we begin
  135.     tempCGrafPort = NULL;
  136.     newPixMap = NULL;
  137.     newDevice = NULL;
  138.     err = noErr;
  139.  
  140.         // save the color table’s current state and make sure it isn’t purgeable
  141.     if (colors != NULL)
  142.     {
  143.         savedState = HGetState( (Handle)colors );
  144.         HNoPurge( (Handle)colors );
  145.     }
  146.  
  147.         // calculate the number of bytes per row in the off-screen PixMap
  148.     bytesPerRow = ((depth * (bounds->right - bounds->left) + 31) >> 5) << 2;
  149.  
  150.         // get the current QuickDraw version
  151.     err = Gestalt(gestaltQuickdrawVersion, &qdVersion);
  152.  
  153.         // this will always be noErr, but I can't stand not checking anyway!
  154.     if (err == noErr)
  155.     {
  156.             // make sure depth is indexed or depth is direct and 32-Bit QD installed
  157.         if (depth == 1 || depth == 2 || depth == 4 || depth == 8 ||
  158.             ((depth == 16 || depth == 32) && qdVersion >= gestalt32BitQD))
  159.         {
  160.                 // maximum number of bytes per row is 16,382; make sure within range
  161.             if (bytesPerRow <= kMaxRowBytes)
  162.             {
  163.                     // make sure a color table is provided if the depth is indexed
  164.                 if (depth <= 8)
  165.                     if (colors == NULL)
  166.                             // indexed depth and clut is NIL; is parameter err
  167.                         err = paramErr;
  168.                 }
  169.             else
  170.                     // # of bytes per row is more than 16,382; is parameter err
  171.                 err = paramErr;
  172.         }
  173.         else
  174.                 // pixel depth isn’t valid; is parameter err
  175.             err = paramErr;
  176.     }
  177.  
  178.         // if sanity checks succeed, then allocate a new CGrafPort
  179.     if (err == noErr)
  180.     {
  181.         tempCGrafPort = (CGrafPtr)NewPtr(sizeof (CGrafPort) );
  182.         if (tempCGrafPort != NULL)
  183.         {
  184.                 // save the current port
  185.             GetPort( &savedPort );
  186.  
  187.                 // initialize the new CGrafPort and make it the current port
  188.             OpenCPort( tempCGrafPort );
  189.  
  190.                 // set portRect, visRgn, and clipRgn to the given bounds rect
  191.             tempCGrafPort->portRect = *bounds;
  192.             RectRgn( tempCGrafPort->visRgn, bounds );
  193.             ClipRect( bounds );
  194.  
  195.                 // initialize the new PixMap for off-screen drawing
  196.             err = SWSetUpPixMap(tempCGrafPort->portPixMap, depth, bounds, colors, bytesPerRow);
  197.  
  198.             if (err == noErr)
  199.             {
  200.                 EraseRect(bounds);
  201.  
  202.                     // grab the initialized PixMap handle
  203.                 newPixMap = tempCGrafPort->portPixMap;
  204.             }
  205.  
  206.                 // restore the saved port
  207.             SetPort(savedPort);
  208.         }
  209.         else
  210.             err = MemError();
  211.     }
  212.  
  213.         // restore the given state of the color table
  214.     if (colors != NULL)
  215.         HSetState((Handle)colors, savedState);
  216.  
  217.         // one last look around the house before we go...
  218.     if (err != noErr)
  219.     {
  220.             // some err occurred; dispose of everything we allocated
  221.         if (newPixMap != NULL)
  222.         {
  223.             DisposCTable((**newPixMap).pmTable);
  224.             DisposPtr((**newPixMap).baseAddr);
  225.         }
  226.  
  227.         if (tempCGrafPort != NULL)
  228.         {
  229.             CloseCPort(tempCGrafPort);
  230.             DisposPtr((Ptr)tempCGrafPort);
  231.         }
  232.     }
  233.     else
  234.     {
  235.             // everything’s OK; return refs to off-screen CGrafPort
  236.         *newCGrafPort = tempCGrafPort;
  237.     }
  238.  
  239.     return err;
  240. }
  241.  
  242.  
  243. ///--------------------------------------------------------------------------------------
  244. // SWCreateCGrafPortFromCIconMask
  245. ///--------------------------------------------------------------------------------------
  246.  
  247. SW_FUNC OSErr SWCreateCGrafPortFromCIconMask(
  248.     CGrafPtr *newCGrafPort,
  249.     CIconHandle cIconH)
  250. {
  251.     OSErr err;
  252.     GrafPtr savePort;
  253.     char saveState;
  254.     CGrafPtr tempCGrafPort;
  255.     BitMap maskBitMap;
  256.     PixMapHandle maskPixMapH;
  257.  
  258.     *newCGrafPort = NULL;
  259.  
  260.     GetPort(&savePort);
  261.  
  262.     saveState = HGetState((Handle)cIconH);
  263.     HLock((Handle)cIconH);
  264.  
  265.     maskBitMap.rowBytes = (**cIconH).iconMask.rowBytes;
  266.     maskBitMap.bounds = (**cIconH).iconMask.bounds;
  267.     maskBitMap.baseAddr = (Ptr)(**cIconH).iconMaskData;
  268.  
  269.     err = SWCreateBestCGrafPort(&tempCGrafPort, &maskBitMap.bounds);
  270.  
  271.     if (err == noErr)
  272.     {
  273.         maskPixMapH = tempCGrafPort->portPixMap;
  274.         HLock((Handle)maskPixMapH);
  275.  
  276.         SetPort((GrafPtr)tempCGrafPort);
  277.  
  278.         CopyBits(&maskBitMap, (BitMapPtr)*maskPixMapH,
  279.                     &maskBitMap.bounds, &maskBitMap.bounds,
  280.                     srcCopy, NULL);
  281.  
  282.         HUnlock((Handle)maskPixMapH);
  283.  
  284.         *newCGrafPort = tempCGrafPort;
  285.     }
  286.  
  287.     HSetState((Handle)cIconH, saveState);
  288.     SetPort(savePort);
  289.  
  290.     return err;
  291. }
  292.  
  293.  
  294. ///--------------------------------------------------------------------------------------
  295. // SWCreateCGrafPortFromPict
  296. ///--------------------------------------------------------------------------------------
  297.  
  298. SW_FUNC OSErr SWCreateCGrafPortFromPict(
  299.     CGrafPtr *newCGrafPort,
  300.     PicHandle srcPictH)
  301. {
  302.     OSErr err;
  303.     GrafPtr savePort;
  304.     GWorldPtr tempCGrafPort;
  305.     Rect pictRect;
  306.  
  307.     *newCGrafPort = NULL;
  308.  
  309.     GetPort(&savePort);
  310.  
  311.     pictRect.left = 0;
  312.     pictRect.top = 0;
  313.     pictRect.right = (**srcPictH).picFrame.right - (**srcPictH).picFrame.left;
  314.     pictRect.bottom = (**srcPictH).picFrame.bottom - (**srcPictH).picFrame.top;
  315.  
  316.     err = SWCreateBestCGrafPort(&tempCGrafPort, &pictRect);
  317.  
  318.     if (err == noErr)
  319.     {
  320.         SetPort((GrafPtr)tempCGrafPort);
  321.  
  322.         DrawPicture(srcPictH, &pictRect);
  323.  
  324.         *newCGrafPort = tempCGrafPort;
  325.     }
  326.  
  327.     SetPort(savePort);
  328.  
  329.     return err;
  330. }
  331.  
  332.  
  333. ///--------------------------------------------------------------------------------------
  334. // SWCreateCGrafPortFromPictResource
  335. ///--------------------------------------------------------------------------------------
  336.  
  337. SW_FUNC OSErr SWCreateCGrafPortFromPictResource(
  338.     CGrafPtr *newCGrafPort,
  339.     short pictResID)
  340. {
  341.     OSErr err = noErr;
  342.     PicHandle newPictH;
  343.  
  344.     *newCGrafPort = NULL;
  345.  
  346.     newPictH = GetPicture(pictResID);
  347.  
  348.     if (newPictH != NULL)
  349.     {
  350.         err = SWCreateCGrafPortFromPict(newCGrafPort, newPictH);
  351.  
  352.         ReleaseResource((Handle)newPictH);
  353.     }
  354.     else
  355.     {
  356.         err = ResError();
  357.  
  358.         if (err == noErr)
  359.         {
  360.             err = resNotFound;
  361.         }
  362.     }
  363.  
  364.     return err;
  365. }
  366.  
  367.  
  368. ///--------------------------------------------------------------------------------------
  369. // SWSetUpPixMap                                                    Adapted from code by Forrest Tanaka
  370. ///--------------------------------------------------------------------------------------
  371.  
  372. #define kDefaultRes 0x00480000 // Default resolution is 72 DPI; Fixed type
  373.  
  374. SW_FUNC OSErr SWSetUpPixMap(
  375.     PixMapHandle    aPixMap,            // Handle to the PixMap being initialized
  376.     short                depth,            // Desired number of bits/pixel in off-screen
  377.     Rect                *bounds,            // Bounding rectangle of off-screen
  378.     CTabHandle        colors,            // Color table to assign to off-screen
  379.     short                bytesPerRow)    // Number of bytes per row in the PixMap
  380. {
  381.     CTabHandle    newColors;        // color table used for the off-screen PixMap
  382.     Ptr            offBaseAddr;    // pointer to the off-screen pixel image
  383.     OSErr            err;                // returns err code
  384.  
  385.     err = noErr;
  386.     newColors = NULL;
  387.     offBaseAddr = NULL;
  388.  
  389.         // clone the clut if indexed color; allocate a dummy clut if direct color
  390.     if (depth <= 8)
  391.     {
  392.         newColors = colors;
  393.         err = HandToHand( (Handle *)&newColors );
  394.     }
  395.     else
  396.     {
  397.         newColors = (CTabHandle)NewHandle(sizeof(ColorTable) - sizeof(CSpecArray));
  398.         err = MemError();
  399.     }
  400.  
  401.     if (err == noErr)
  402.     {
  403.             // allocate pixel image; long integer multiplication avoids overflow
  404.         offBaseAddr = NewPtr((Size)bytesPerRow *
  405.                                 (bounds->bottom - bounds->top) );
  406.         if (offBaseAddr != NULL)
  407.         {
  408.                 // initialize fields common to indexed and direct PixMaps
  409.             (**aPixMap).baseAddr = offBaseAddr;  // Point to image
  410.             (**aPixMap).rowBytes = bytesPerRow | // MSB set for PixMap
  411.                     0x8000;
  412.             (**aPixMap).bounds = *bounds;        // Use given bounds
  413.             (**aPixMap).pmVersion = 0;           // No special stuff
  414.             (**aPixMap).packType = 0;            // Default PICT pack
  415.             (**aPixMap).packSize = 0;            // Always zero in mem
  416.             (**aPixMap).hRes = kDefaultRes;      // 72 DPI default res
  417.             (**aPixMap).vRes = kDefaultRes;      // 72 DPI default res
  418.             (**aPixMap).pixelSize = depth;       // Set # bits/pixel
  419.             (**aPixMap).planeBytes = 0;          // Not used
  420.             (**aPixMap).pmReserved = 0;          // Not used
  421.  
  422.                 // initialize fields specific to indexed and direct PixMaps
  423.             if (depth <= 8)
  424.             {
  425.                     // PixMap is indexed
  426.                 (**aPixMap).pixelType = 0;            // Indicates indexed
  427.                 (**aPixMap).cmpCount = 1;            // Have 1 component
  428.                 (**aPixMap).cmpSize = depth;        // Component size=depth
  429.                 (**aPixMap).pmTable = newColors;    // Handle to CLUT
  430.             }
  431.             else
  432.             {
  433.                     // PixMap is direct
  434.                 (**aPixMap).pixelType = RGBDirect;    // Indicates direct
  435.                 (**aPixMap).cmpCount = 3;                // Have 3 components
  436.                 if (depth == 16)
  437.                     (**aPixMap).cmpSize = 5;            // 5 bits/component
  438.                 else
  439.                     (**aPixMap).cmpSize = 8;            // 8 bits/component
  440.                 (**newColors).ctSeed = 3 * (**aPixMap).cmpSize;
  441.                 (**newColors).ctFlags = 0;
  442.                 (**newColors).ctSize = 0;
  443.                 (**aPixMap).pmTable = newColors;
  444.             }
  445.         }
  446.         else
  447.             err = MemError();
  448.     }
  449.     else
  450.         newColors = NULL;
  451.  
  452.         // if no errors occurred, return a handle to the new off-screen PixMap
  453.     if (err != noErr)
  454.     {
  455.         if (newColors != NULL)
  456.             DisposCTable( newColors );
  457.     }
  458.  
  459.         // return the err code
  460.     return err;
  461. }
  462.  
  463.  
  464.  
  465. ///--------------------------------------------------------------------------------------
  466. // SWCreateGDevice                                                Adapted from code by Forrest Tanaka
  467. ///--------------------------------------------------------------------------------------
  468.  
  469. #define kITabRes 4 // Inverse-table resolution
  470.  
  471. SW_FUNC OSErr SWCreateGDevice(
  472.     GDHandle            *retGDevice,    // returns a handle to the new GDevice
  473.     PixMapHandle    basePixMap)        // handle to the PixMap to base GDevice on
  474. {
  475.     GDHandle            newDevice;        // handle to the new GDevice
  476.     ITabHandle        embryoITab;        // handle to the embryonic inverse table
  477.     Rect                deviceRect;        // rectangle of GDevice
  478.     OSErr                err;                // error code
  479.  
  480.         // initialize a few things before we begin
  481.     err = noErr;
  482.     newDevice = NULL;
  483.     embryoITab = NULL;
  484.  
  485.         // allocate memory for the new GDevice
  486.     newDevice = (GDHandle)NewHandle( sizeof (GDevice) );
  487.     if (newDevice != NULL)
  488.     {
  489.             // allocate the embryonic inverse table
  490.         embryoITab = (ITabHandle)NewHandleClear( 2 );
  491.         if (embryoITab != NULL)
  492.         {
  493.                 // set rectangle of device to PixMap bounds
  494.             deviceRect = (**basePixMap).bounds;
  495.  
  496.             // Initialize the new GDevice fields
  497.             (**newDevice).gdRefNum = 0;                // Only used for screens
  498.             (**newDevice).gdID = 0;                        // Won’t normally use
  499.             if ((**basePixMap).pixelSize <= 8)
  500.                 (**newDevice).gdType = clutType;        // Depth≤8; clut device
  501.             else
  502.                 (**newDevice).gdType = directType;    // Depth>8; direct device
  503.             (**newDevice).gdITable = embryoITab;    // 2-byte handle for now
  504.             (**newDevice).gdResPref = kITabRes;        // Normal inv table res
  505.             (**newDevice).gdSearchProc = NULL;        // No color-search proc
  506.             (**newDevice).gdCompProc = NULL;            // No complement proc
  507.             (**newDevice).gdFlags = 0;                    // Will set these later
  508.             (**newDevice).gdPMap = basePixMap;        // Reference our PixMap
  509.             (**newDevice).gdRefCon = 0;                // Won’t normally use
  510.             (**newDevice).gdNextGD = NULL;            // Not in GDevice list
  511.             (**newDevice).gdRect = deviceRect;        // Use PixMap dimensions
  512.             (**newDevice).gdMode = -1;                    // For nonscreens
  513.             (**newDevice).gdCCBytes = 0;                // Only used for screens
  514.             (**newDevice).gdCCDepth = 0;                // Only used for screens
  515.             (**newDevice).gdCCXData = 0;                // Only used for screens
  516.             (**newDevice).gdCCXMask = 0;                // Only used for screens
  517.             (**newDevice).gdReserved = 0;                // Currently unused
  518.  
  519.                 // set color-device bit if PixMap isn’t black & white
  520.             if ((**basePixMap).pixelSize > 1)
  521.                 SetDeviceAttribute( newDevice, gdDevType, true );
  522.  
  523.                 // set bit to indicate that the GDevice has no video driver
  524.             SetDeviceAttribute( newDevice, noDriver, true );
  525.  
  526.                 // initialize the inverse table
  527.             if ((**basePixMap).pixelSize <= 8)
  528.             {
  529.                 MakeITable( (**basePixMap).pmTable, (**newDevice).gdITable, (**newDevice).gdResPref );
  530.                 err = QDError();
  531.             }
  532.         }
  533.         else
  534.             err = MemError();
  535.     }
  536.     else
  537.         err = MemError();
  538.  
  539.         // handle any errors along the way
  540.     if (err != noErr)
  541.     {
  542.         if (embryoITab != NULL)
  543.             DisposHandle( (Handle)embryoITab );
  544.         if (newDevice != NULL)
  545.             DisposHandle( (Handle)newDevice );
  546.     }
  547.     else
  548.         *retGDevice = newDevice;
  549.  
  550.         // return a handle to the new GDevice
  551.     return err;
  552. }
  553.  
  554.  
  555. ///--------------------------------------------------------------------------------------
  556. // SWDisposeCGrafPort                                            Adapted from code by Forrest Tanaka
  557. ///--------------------------------------------------------------------------------------
  558.  
  559. SW_FUNC void SWDisposeCGrafPort(
  560.     CGrafPtr doomedPort)        // pointer to the CGrafPort to be disposed of
  561. {
  562.     CGrafPtr currPort;        // pointer to the current port
  563.  
  564.         // check to see whether the doomed CGrafPort is the current port
  565.     GetPort((GrafPtr *)&currPort);
  566.  
  567.     if (currPort == doomedPort)
  568.     {
  569.             // it is; set current port to Window Manager CGrafPort
  570.         GetCWMgrPort(&currPort);
  571.         SetPort((GrafPtr)currPort);
  572.     }
  573.  
  574.     DisposPtr((**doomedPort->portPixMap).baseAddr);
  575.  
  576.     if ((**doomedPort->portPixMap).pmTable != NULL)
  577.     {
  578.         DisposCTable((**doomedPort->portPixMap).pmTable);
  579.     }
  580.  
  581.     CloseCPort(doomedPort);
  582.     DisposPtr((Ptr)doomedPort);
  583. }
  584.  
  585.  
  586. ///--------------------------------------------------------------------------------------
  587. // SWCreateGrafPort                                            Adapted from code by Forrest Tanaka.
  588. ///--------------------------------------------------------------------------------------
  589.  
  590. SW_FUNC OSErr SWCreateGrafPort(
  591.     GrafPtr* newPort,
  592.     Rect* newPortRect)
  593. {
  594.     OSErr err = noErr;
  595.     GrafPtr savePort;        // save port for later restore
  596.     GrafPtr localPort;    // local copy of GrafPort
  597.     Rect localPortRect;    // local copy of bounds
  598.  
  599.     *newPort = NULL;
  600.  
  601.         // save off the current port
  602.     GetPort(&savePort);
  603.  
  604.         // set the top-left corner of bounds to (0,0)
  605.     localPortRect = *newPortRect;
  606.     OffsetRect(&localPortRect, -newPortRect->left, -newPortRect->top);
  607.  
  608.         // allocate a new GrafPort
  609.     localPort = (GrafPtr)NewPtrClear(sizeof(GrafPort));
  610.  
  611.     if (localPort != NULL)
  612.     {
  613.             // initialize the new port and make the current port
  614.         OpenPort(localPort);
  615.         SetPort(localPort);
  616.         ForeColor(blackColor);
  617.         BackColor(whiteColor);
  618.  
  619.             // initialize and allocate the bitmap
  620.         localPort->portBits.bounds = localPortRect;
  621.           localPort->portBits.rowBytes = ((localPortRect.right + 15) >> 4) << 1;
  622.         localPort->portBits.baseAddr = NewPtrClear(localPort->portBits.rowBytes *
  623.                                                                 (long)localPortRect.bottom);
  624.  
  625.         if (localPort->portBits.baseAddr != NULL)
  626.         {
  627.                 // clean up the new port
  628.             localPort->portRect = localPortRect;
  629.             ClipRect(&localPortRect);
  630.             RectRgn(localPort->visRgn, &localPortRect);
  631.             EraseRect(&localPortRect);
  632.  
  633.             *newPort = localPort;
  634.         }
  635.         else // allocation failed
  636.         {
  637.                 // capture the error
  638.             err = MemError();
  639.  
  640.                 // deallocate the port
  641.             ClosePort(localPort);
  642.             DisposPtr((Ptr)localPort);
  643.         }
  644.     }
  645.     else
  646.     {
  647.         err = MemError();
  648.     }
  649.  
  650.     SetPort(savePort);
  651.  
  652.     return err;
  653. }
  654.  
  655.  
  656. ///--------------------------------------------------------------------------------------
  657. // SWCreateGrafPortFromCIconMask
  658. ///--------------------------------------------------------------------------------------
  659.  
  660. SW_FUNC OSErr SWCreateGrafPortFromCIconMask(
  661.     GrafPtr *newGrafPort,
  662.     CIconHandle cIconH)
  663. {
  664.     OSErr err;
  665.     GrafPtr savePort;
  666.     char saveState;
  667.     GrafPtr tempGrafPort;
  668.     BitMap maskBitMap;
  669.  
  670.     *newGrafPort = NULL;
  671.  
  672.     GetPort(&savePort);
  673.  
  674.     saveState = HGetState((Handle)cIconH);
  675.     HLock((Handle)cIconH);
  676.  
  677.     maskBitMap.rowBytes = (**cIconH).iconMask.rowBytes;
  678.     maskBitMap.bounds = (**cIconH).iconMask.bounds;
  679.     maskBitMap.baseAddr = (Ptr)(**cIconH).iconMaskData;
  680.  
  681.     err = SWCreateGrafPort(&tempGrafPort, &maskBitMap.bounds);
  682.  
  683.     if (err == noErr)
  684.     {
  685.         SetPort(tempGrafPort);
  686.  
  687.         CopyBits(&maskBitMap, &tempGrafPort->portBits,
  688.                     &maskBitMap.bounds, &maskBitMap.bounds,
  689.                     srcCopy, NULL);
  690.  
  691.         *newGrafPort = tempGrafPort;
  692.     }
  693.  
  694.     HSetState((Handle)cIconH, saveState);
  695.     SetPort(savePort);
  696.  
  697.     return err;
  698. }
  699.  
  700.  
  701. ///--------------------------------------------------------------------------------------
  702. // SWCreateGrafPortFromPict
  703. ///--------------------------------------------------------------------------------------
  704.  
  705. SW_FUNC OSErr SWCreateGrafPortFromPict(
  706.     GrafPtr *offScrnPort,
  707.     PicHandle srcPictH)
  708. {
  709.     OSErr            err;
  710.     GrafPtr        savePort;
  711.     Rect            tmpRect;
  712.  
  713.     GetPort(&savePort);
  714.  
  715.     tmpRect.left = tmpRect.top = 0;
  716.     tmpRect.right = (**srcPictH).picFrame.right - (**srcPictH).picFrame.left;
  717.     tmpRect.bottom = (**srcPictH).picFrame.bottom - (**srcPictH).picFrame.top;
  718.  
  719.         //    create a port
  720.     err = SWCreateGrafPort(offScrnPort, &tmpRect);
  721.  
  722.     if (err == noErr)
  723.     {
  724.         SetPort(*offScrnPort);
  725.  
  726.             //    draw the picture
  727.         DrawPicture(srcPictH, &tmpRect);
  728.     }
  729.  
  730.     SetPort(savePort);
  731.  
  732.     return err;
  733. }
  734.  
  735. ///--------------------------------------------------------------------------------------
  736. // SWCreateGrafPortFromPictResource
  737. //
  738. //    this routine will set up an offscreen port, and draw a pict into it
  739. //    the offscreen port is the exact size of the pict
  740. ///--------------------------------------------------------------------------------------
  741.  
  742. SW_FUNC OSErr SWCreateGrafPortFromPictResource(
  743.     GrafPtr *offScrnPort,
  744.     short pictResID)
  745. {
  746.     OSErr            err;
  747.     GrafPtr        savePort;
  748.     PicHandle    newPictH;
  749.  
  750.     GetPort(&savePort);
  751.  
  752.     newPictH = GetPicture(pictResID);
  753.  
  754.     if (newPictH != NULL)
  755.     {
  756.         err = SWCreateGrafPortFromPict(offScrnPort, newPictH);
  757.  
  758.         ReleaseResource((Handle)newPictH);
  759.     }
  760.     else
  761.     {
  762.         err = ResError();
  763.  
  764.         if (err == noErr)
  765.         {
  766.             err = resNotFound;
  767.         }
  768.     }
  769.  
  770.     SetPort(savePort);
  771.  
  772.     return err;
  773. }
  774.  
  775.  
  776. ///--------------------------------------------------------------------------------------
  777. // SWDisposeGrafPort                                            Adapted from code by Forrest Tanaka.
  778. ///--------------------------------------------------------------------------------------
  779.  
  780. SW_FUNC void SWDisposeGrafPort(
  781.     GrafPtr doomedPort)
  782. {
  783.     ClosePort(doomedPort);
  784.     DisposPtr(doomedPort->portBits.baseAddr);
  785.     DisposPtr((Ptr)doomedPort);
  786. }
  787.  
  788.  
  789. ///--------------------------------------------------------------------------------------
  790. // SWCreateRegionFromCIconMask
  791. ///--------------------------------------------------------------------------------------
  792.  
  793. SW_FUNC OSErr SWCreateRegionFromCIconMask(
  794.     RgnHandle *maskRgn,
  795.     CIconHandle cIconH)
  796. {
  797.     OSErr err = noErr;
  798.     RgnHandle tempMaskRgn;
  799.     char saveState;
  800.     BitMap iconMask;
  801.  
  802.     *maskRgn = NULL;
  803.  
  804.     saveState = HGetState((Handle)cIconH);
  805.     HLock((Handle)cIconH);
  806.  
  807.     iconMask.rowBytes = (**cIconH).iconMask.rowBytes;
  808.     iconMask.bounds = (**cIconH).iconMask.bounds;
  809.     iconMask.baseAddr = (Ptr)(**cIconH).iconMaskData;
  810.  
  811.     tempMaskRgn = NewRgn();
  812.  
  813.     if (tempMaskRgn != NULL)
  814.     {
  815.         if (SWHasGWorlds())
  816.         {
  817.             err = BitMapToRegion(tempMaskRgn, &iconMask);
  818.         }
  819.  
  820.         if (err == noErr)
  821.         {
  822.             *maskRgn = tempMaskRgn;
  823.         }
  824.         else
  825.         {
  826.             DisposeRgn(tempMaskRgn);
  827.         }
  828.     }
  829.     else
  830.     {
  831.         err = MemError();
  832.     }
  833.  
  834.     HSetState((Handle)cIconH, saveState);
  835.  
  836.     return err;
  837. }
  838.  
  839.  
  840. ///--------------------------------------------------------------------------------------
  841. // SWCreateRegionFromPict
  842. ///--------------------------------------------------------------------------------------
  843.  
  844. SW_FUNC OSErr SWCreateRegionFromPict(
  845.     RgnHandle *pictRgnH,
  846.     PicHandle srcPictH)
  847. {
  848.     OSErr err;
  849.     RgnHandle tempRgnH;
  850.     GrafPtr savePort, offScrnPort;
  851.  
  852.     *pictRgnH = NULL;
  853.  
  854.     GetPort(&savePort);
  855.  
  856.     err = SWCreateGrafPortFromPict(&offScrnPort, srcPictH);
  857.  
  858.     if (err == noErr)
  859.     {
  860.         SetPort(offScrnPort);
  861.  
  862.         tempRgnH = NewRgn();
  863.  
  864.         if (tempRgnH != NULL)
  865.         {
  866.             if (SWHasGWorlds())
  867.             {
  868.                 err = BitMapToRegion(tempRgnH, &offScrnPort->portBits);
  869.             }
  870.  
  871.             if (err == noErr)
  872.             {
  873.                 *pictRgnH = tempRgnH;
  874.             }
  875.             else
  876.             {
  877.                 DisposeRgn(tempRgnH);
  878.             }
  879.         }
  880.         else
  881.         {
  882.             err = MemError();
  883.         }
  884.  
  885.         SetPort(savePort);
  886.         SWDisposeGrafPort(offScrnPort);
  887.     }
  888.  
  889.     return err;
  890. }
  891.  
  892.  
  893. ///--------------------------------------------------------------------------------------
  894. // SWCreateRegionFromPictResource
  895. ///--------------------------------------------------------------------------------------
  896.  
  897. SW_FUNC OSErr SWCreateRegionFromPictResource(
  898.     RgnHandle *pictRgnH,
  899.     short pictResID)
  900. {
  901.     OSErr            err;
  902.     PicHandle    newPictH;
  903.  
  904.     newPictH = GetPicture(pictResID);
  905.  
  906.     if (newPictH != NULL)
  907.     {
  908.         err = SWCreateRegionFromPict(pictRgnH, newPictH);
  909.  
  910.         ReleaseResource((Handle)newPictH);
  911.     }
  912.     else
  913.     {
  914.         err = ResError();
  915.  
  916.         if (err == noErr)
  917.         {
  918.             err = resNotFound;
  919.         }
  920.     }
  921.  
  922.     return err;
  923. }
  924.  
  925.  
  926. ///--------------------------------------------------------------------------------------
  927. // SWGetCIcon
  928. ///--------------------------------------------------------------------------------------
  929.  
  930. SW_FUNC OSErr SWGetCIcon(
  931.     CIconHandle* cIconH,
  932.     short iconResID)
  933. {
  934.     OSErr err = noErr;
  935.     CIconHandle tempCIconH;
  936.  
  937.     *cIconH = NULL;
  938.  
  939.     if (SWHasColorQuickDraw())
  940.     {
  941.         tempCIconH = GetCIcon(iconResID);
  942.  
  943.         if (tempCIconH == NULL)
  944.         {
  945.                 // hmmm, could be a resource error...
  946.             err = ResError();
  947.  
  948.             if (err == noErr)
  949.             {
  950.                     // or, a memory error...
  951.                 err = MemError();
  952.             }
  953.  
  954.             if (err == noErr)
  955.             {
  956.                     // ...well then lets make up an error!
  957.                 err = resNotFound;
  958.             }
  959.         }
  960.     }
  961.     else
  962.     {
  963.             // don't ever do this if color QuickDraw is around!
  964.         tempCIconH = (CIconHandle)GetResource(kColorIconResType, iconResID);
  965.  
  966.         if (tempCIconH != NULL)
  967.         {
  968.             DetachResource((Handle)tempCIconH);
  969.         }
  970.         else
  971.         {
  972.             err = ResError();
  973.  
  974.             if (err == noErr)
  975.             {
  976.                 err = resNotFound;
  977.             }
  978.         }
  979.     }
  980.  
  981.     if (err == noErr)
  982.     {
  983.         *cIconH = tempCIconH;
  984.     }
  985.  
  986.     return err;
  987. }
  988.  
  989.  
  990. ///--------------------------------------------------------------------------------------
  991. // SWPlotCIcon
  992. ///--------------------------------------------------------------------------------------
  993.  
  994. SW_FUNC OSErr SWPlotCIcon(
  995.     CIconHandle cIconH,
  996.     Rect* iconRect)
  997. {
  998.     OSErr err = noErr;
  999.     char saveState;
  1000.     BitMap iconBitMap, maskBitMap;
  1001.     GrafPtr curPort;
  1002.  
  1003.     if (SWHasColorQuickDraw())
  1004.     {
  1005.         PlotCIcon(iconRect, cIconH);
  1006.     }
  1007.     else
  1008.     {
  1009.         saveState = HGetState((Handle)cIconH);
  1010.         HLock((Handle)cIconH);
  1011.  
  1012.         maskBitMap.rowBytes = (**cIconH).iconMask.rowBytes;
  1013.         maskBitMap.bounds = (**cIconH).iconMask.bounds;
  1014.         maskBitMap.baseAddr = (Ptr)(**cIconH).iconMaskData;
  1015.  
  1016.         iconBitMap.rowBytes = (**cIconH).iconBMap.rowBytes;
  1017.         iconBitMap.bounds = (**cIconH).iconBMap.bounds;
  1018.         iconBitMap.baseAddr = maskBitMap.baseAddr +
  1019.                 (maskBitMap.rowBytes * (maskBitMap.bounds.bottom - maskBitMap.bounds.top));
  1020.  
  1021.         GetPort(&curPort);
  1022.  
  1023.         CopyMask(&iconBitMap, &maskBitMap, &curPort->portBits,
  1024.                 &iconBitMap.bounds, &maskBitMap.bounds, iconRect);
  1025.  
  1026.         HSetState((Handle)cIconH, saveState);
  1027.     }
  1028.     
  1029.     return err;
  1030. }
  1031.  
  1032.  
  1033. ///--------------------------------------------------------------------------------------
  1034. // SWPlotCIcon
  1035. ///--------------------------------------------------------------------------------------
  1036.  
  1037. SW_FUNC void SWDisposeCIcon(
  1038.     CIconHandle cIconH)
  1039. {
  1040.     if (SWHasColorQuickDraw())
  1041.     {
  1042.         DisposeCIcon(cIconH);
  1043.     }
  1044.     else
  1045.     {
  1046.         DisposeHandle((Handle)cIconH);
  1047.     }
  1048. }
  1049.  
  1050.  
  1051. ///--------------------------------------------------------------------------------------
  1052. // SWCreateOptimumGWorld
  1053. //
  1054. //    create a new GWorld optimized for speed in copying
  1055. //    to the graphics device that intersects the given rect.
  1056. ///--------------------------------------------------------------------------------------
  1057.  
  1058. SW_FUNC OSErr SWCreateOptimumGWorld(
  1059.     GWorldPtr *optGWorld,
  1060.     Rect *devRect)
  1061. {
  1062.     OSErr err;
  1063.     CGrafPtr saveCPort;
  1064.     GDHandle saveGDevice;
  1065.     GWorldPtr tempGWorld;
  1066.     PixMapHandle pixMapH;
  1067.     Rect tempRect = *devRect;
  1068.  
  1069.     *optGWorld = NULL;
  1070.  
  1071.     GetGWorld(&saveCPort, &saveGDevice);
  1072.  
  1073.     LocalToGlobal((Point *)&tempRect.top);
  1074.     LocalToGlobal((Point *)&tempRect.bottom);
  1075.  
  1076.     err = NewGWorld(&tempGWorld, 0, &tempRect, NULL, NULL, noNewDevice);
  1077.  
  1078.     if (err == noErr)
  1079.     {
  1080.         SetGWorld(tempGWorld, NULL);
  1081.  
  1082.         pixMapH = GetGWorldPixMap(tempGWorld);
  1083.  
  1084.         if (LockPixels(pixMapH))
  1085.         {
  1086.             EraseRect(&tempGWorld->portRect);
  1087.  
  1088.             UnlockPixels(pixMapH);
  1089.         }
  1090.  
  1091.         *optGWorld = tempGWorld;
  1092.     }
  1093.  
  1094.     SetGWorld(saveCPort, saveGDevice);
  1095.  
  1096.     return err;
  1097. }
  1098.  
  1099.  
  1100. ///--------------------------------------------------------------------------------------
  1101. // SWCreateGWorldFromPict
  1102. //
  1103. //    creates a offScreen GWorld and draws the specified pict into it
  1104. ///--------------------------------------------------------------------------------------
  1105.  
  1106. SW_FUNC OSErr SWCreateGWorldFromPict(
  1107.     GWorldPtr *pictGWorld,
  1108.     PicHandle pictH)
  1109. {
  1110.     OSErr err;
  1111.     CGrafPtr saveCPort;
  1112.     GDHandle saveGDevice;
  1113.     GWorldPtr tempGWorld;
  1114.     PixMapHandle tempPixHdl;
  1115.     Rect pictRect;
  1116.  
  1117.     *pictGWorld = NULL;
  1118.  
  1119.     GetGWorld(&saveCPort, &saveGDevice);
  1120.  
  1121.     pictRect.left = 0;
  1122.     pictRect.top = 0;
  1123.     pictRect.right = (**pictH).picFrame.right - (**pictH).picFrame.left;
  1124.     pictRect.bottom = (**pictH).picFrame.bottom - (**pictH).picFrame.top;
  1125.  
  1126.     err = SWCreateOptimumGWorld(&tempGWorld, &pictRect);
  1127.  
  1128.     if (err == noErr)
  1129.     {
  1130.         *pictGWorld = tempGWorld;
  1131.  
  1132.         SetGWorld(tempGWorld, NULL);
  1133.  
  1134.         tempPixHdl = GetGWorldPixMap(tempGWorld);
  1135.  
  1136.         if (LockPixels(tempPixHdl))
  1137.         {
  1138.             DrawPicture(pictH, &pictRect);
  1139.  
  1140.             UnlockPixels(tempPixHdl);
  1141.         }
  1142.     }
  1143.  
  1144.     SetGWorld(saveCPort, saveGDevice);
  1145.  
  1146.     return err;
  1147. }
  1148.  
  1149.  
  1150. ///--------------------------------------------------------------------------------------
  1151. // SWCreateGWorldFromPictResource
  1152. ///--------------------------------------------------------------------------------------
  1153.  
  1154. SW_FUNC OSErr SWCreateGWorldFromPictResource(
  1155.     GWorldPtr *pictGWorldP,
  1156.     short pictResID)
  1157. {
  1158.     OSErr err = noErr;
  1159.     PicHandle newPictH;
  1160.  
  1161.     newPictH = GetPicture(pictResID);
  1162.  
  1163.     if (newPictH != NULL)
  1164.     {
  1165.         err = SWCreateGWorldFromPict(pictGWorldP, newPictH);
  1166.  
  1167.         ReleaseResource((Handle)newPictH);
  1168.     }
  1169.     else
  1170.     {
  1171.         err = ResError();
  1172.         
  1173.         if (err == noErr)
  1174.         {
  1175.             err = resNotFound;
  1176.         }
  1177.     }
  1178.  
  1179.     return err;
  1180. }
  1181.  
  1182.  
  1183. ///--------------------------------------------------------------------------------------
  1184. // SWCreateGWorldFromCIconResource
  1185. ///--------------------------------------------------------------------------------------
  1186.  
  1187. SW_FUNC OSErr SWCreateGWorldFromCIconResource(
  1188.     GWorldPtr *iconGWorldP,
  1189.     short iconResID)
  1190. {
  1191.     OSErr err;
  1192.     CIconHandle cIconH;
  1193.  
  1194.     cIconH = GetCIcon(iconResID);
  1195.  
  1196.     if (cIconH != NULL)
  1197.     {
  1198.         HNoPurge((Handle)cIconH);
  1199.  
  1200.         if (iconGWorldP != NULL)
  1201.         {
  1202.             err = SWCreateGWorldFromCIcon(iconGWorldP, cIconH);
  1203.         }
  1204.  
  1205.         DisposeCIcon(cIconH);
  1206.     }
  1207.  
  1208.     return err;
  1209. }
  1210.  
  1211.  
  1212. ///--------------------------------------------------------------------------------------
  1213. // SWCreateGWorldFromCIcon
  1214. ///--------------------------------------------------------------------------------------
  1215.  
  1216. SW_FUNC OSErr SWCreateGWorldFromCIcon(
  1217.     GWorldPtr *iconGWorldP,
  1218.     CIconHandle cIconH)
  1219. {
  1220.     OSErr err;
  1221.     CGrafPtr saveCPort;
  1222.     GDHandle saveGDevice;
  1223.     GWorldPtr tempGWorldP;
  1224.     PixMapHandle iconPixMapH;
  1225.     Rect iconRect;
  1226.  
  1227.     *iconGWorldP = NULL;
  1228.  
  1229.     GetGWorld(&saveCPort, &saveGDevice);
  1230.  
  1231.     iconRect = (**cIconH).iconPMap.bounds;
  1232.     
  1233.     err = SWCreateOptimumGWorld(&tempGWorldP, &iconRect);
  1234.  
  1235.     if (err == noErr)
  1236.     {
  1237.         *iconGWorldP = tempGWorldP;
  1238.  
  1239.         SetGWorld(tempGWorldP, NULL);
  1240.  
  1241.         iconPixMapH = GetGWorldPixMap(tempGWorldP);
  1242.  
  1243.         if (LockPixels(iconPixMapH))
  1244.         {
  1245.             PlotCIcon(&iconRect, cIconH);
  1246.  
  1247.             UnlockPixels(iconPixMapH);
  1248.         }
  1249.     }
  1250.  
  1251.     SetGWorld(saveCPort, saveGDevice);
  1252.  
  1253.     return err;
  1254. }
  1255.  
  1256.  
  1257. ///--------------------------------------------------------------------------------------
  1258. // SWCreateGWorldFromCIconMask
  1259. ///--------------------------------------------------------------------------------------
  1260.  
  1261. SW_FUNC OSErr SWCreateGWorldFromCIconMask(
  1262.     GWorldPtr *maskGWorldP,
  1263.     CIconHandle cIconH)
  1264. {
  1265.     OSErr err;
  1266.     CGrafPtr saveCPort;
  1267.     GDHandle saveGDevice;
  1268.     char saveState;
  1269.     BitMap maskBitMap;
  1270.     GWorldPtr tempGWorldP;
  1271.     PixMapHandle maskPixMapH;
  1272.  
  1273.     GetGWorld(&saveCPort, &saveGDevice);
  1274.  
  1275.     saveState = HGetState((Handle)cIconH);
  1276.     HLock((Handle)cIconH);
  1277.  
  1278.     maskBitMap.rowBytes = (**cIconH).iconMask.rowBytes;
  1279.     maskBitMap.bounds = (**cIconH).iconMask.bounds;
  1280.     maskBitMap.baseAddr = (Ptr)(**cIconH).iconMaskData;
  1281.  
  1282.     err = SWCreateOptimumGWorld(&tempGWorldP, &maskBitMap.bounds);
  1283.  
  1284.     if (err == noErr)
  1285.     {
  1286.         *maskGWorldP = tempGWorldP;
  1287.  
  1288.         SetGWorld(tempGWorldP, NULL);
  1289.  
  1290.         maskPixMapH = GetGWorldPixMap(tempGWorldP);
  1291.  
  1292.         if (LockPixels(maskPixMapH))
  1293.         {
  1294.             CopyBits(&maskBitMap, (BitMapPtr)*maskPixMapH,
  1295.                         &maskBitMap.bounds, &maskBitMap.bounds,
  1296.                         srcCopy, NULL);
  1297.  
  1298.             UnlockPixels(maskPixMapH);
  1299.         }
  1300.     }
  1301.  
  1302.     SetGWorld(saveCPort, saveGDevice);
  1303.  
  1304.     HSetState((Handle)cIconH, saveState);
  1305.  
  1306.     return err;
  1307. }
  1308.  
  1309.  
  1310. ///--------------------------------------------------------------------------------------
  1311. // SWHasColorQuickDraw
  1312. ///--------------------------------------------------------------------------------------
  1313.  
  1314. SW_FUNC Boolean SWHasColorQuickDraw(void)
  1315. {
  1316.     OSErr err;
  1317.     long    gestaltResult;
  1318.  
  1319.     err = Gestalt(gestaltQuickdrawVersion, &gestaltResult);
  1320.  
  1321.     return (err == noErr) && (gestaltResult >= gestalt8BitQD);
  1322. }
  1323.  
  1324.  
  1325. ///--------------------------------------------------------------------------------------
  1326. // SWHasGWorlds
  1327. ///--------------------------------------------------------------------------------------
  1328.  
  1329. SW_FUNC Boolean SWHasGWorlds(void)
  1330. {
  1331.     OSErr err;
  1332.     long    gestaltResult;
  1333.  
  1334.     err = Gestalt(gestaltQuickdrawVersion, &gestaltResult);
  1335.  
  1336.     return (err == noErr) && (((gestaltResult > gestaltOriginalQD) &&
  1337.             (gestaltResult < gestalt8BitQD)) || (gestaltResult >= gestalt32BitQD));
  1338. }
  1339.